package org.finmanager.budget;

import org.finmanager.core.FinManager;
import org.finmanager.core.Item;
import org.finmanager.data.CategoryList;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Observable;
import java.util.Observer;

/**
 * Created by Kelvin on 26/4/2014.
 */

//A class that defining different models(functions) 
//Those models will be used in the BudgetManagerController.java
public class BudgetModel implements Observer {
	private FinManager finManager;

	private BudgetTableModel budgetTableModel;

	public BudgetModel(FinManager finManager) {
		this.finManager = finManager;
		budgetTableModel = new BudgetTableModel(finManager.getBudgetList());
	}

	public BudgetTableModel getBudgetTableModel() {
		return budgetTableModel;
	}

	public void addBudget(Budget budget) {
		Double budgetUsed = findBudgetUsed(budget);
		budget.setRemaining(budget.getAmount() - budgetUsed);
		finManager.getBudgetList().addBudget(budget);
		int index = finManager.getBudgetList().getBudgetCount() - 1;
		budgetTableModel.fireTableRowsInserted(index, index);
	}

	public void deleteBudget(int index) {
		finManager.getBudgetList().deleteBudget(index);
		budgetTableModel.fireTableRowsDeleted(index, index);
	}

	public void updateAllBudgets() {
		for (Budget budget : finManager.getBudgetList().getList()) {
			Double budgetUsed = findBudgetUsed(budget);
			budget.setRemaining(budget.getAmount() - budgetUsed);
		}
		budgetTableModel.fireTableDataChanged();
		finManager.getBudgetList().saveFile();
	}

	private Double findBudgetUsed(Budget budget) {
		Double amountUsed = 0.0;
		for (Item item : finManager.getItemList().getList()) {
			if ((item.getCategory().equals(budget.getCategory()) || budget.getCategory().equals(CategoryList.ALL_CATEGORIES_FLAG)) && checkItemTimeConstraint(budget, item))
				amountUsed += item.getAmount();
		}
		return amountUsed;
	}

	private Boolean checkItemTimeConstraint(Budget budget, Item item) {
		return (budget.getDate().get(Calendar.MONTH) == item.getDate().get(Calendar.MONTH) && budget.getDate().get(Calendar.YEAR) == item.getDate().get(Calendar.YEAR));
	}

	public ArrayList<Budget> findAlmostDepletedBudgets() {
		ArrayList<Budget> budgets = new ArrayList<Budget>();
		for (Budget budget : finManager.getBudgetList().getList()) {
			if (budget.getDate().get(Calendar.YEAR) == Calendar.getInstance().get(Calendar.YEAR) &&
					budget.getDate().get(Calendar.MONTH) == Calendar.getInstance().get(Calendar.MONTH) &&
					budget.getRemaining() / budget.getAmount() <= 0.1)
				budgets.add(budget);
		}
		return budgets;
	}

	@Override
	public void update(Observable o, Object arg) {
		updateAllBudgets();
	}
}
